package com.yeskery.nut.extend.i18n;

import com.yeskery.nut.core.NutException;
import com.yeskery.nut.util.IOUtils;
import com.yeskery.nut.util.StringUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Stream;

/**
 * 消息资源对象
 * @author sprout
 * 2022-05-28 11:50
 */
public class MessageResource {

    /** 消息前缀 */
    private static final String RESOURCE_FILE_PREFIX = "messages_";

    /** 消息后缀 */
    private static final String RESOURCE_FILE_POSTFIX = ".properties";

    /** 默认的消息名称 */
    private static final String RESOURCE_FILE_NAME = "messages.properties";

    /** 消息资源map */
    private final Map<Locale, Properties> localeResources = new HashMap<>();

    /** 默认的消息资源 */
    private final Properties defaultResource = new Properties();

    /**
     * 构建消息资源对象
     */
    public MessageResource() {
        this("");
    }

    /**
     * 构建消息资源对象
     * @param path 资源文件路径，相对路径classpath
     */
    public MessageResource(String path) {
        try {
            // 处理默认资源文件
            URI classPathUrlUri = ClassLoader.getSystemResource(path).toURI();
            FileSystem fileSystem = IOUtils.initFileSystem(classPathUrlUri);

            Path classPath = Paths.get(classPathUrlUri);
            Path defaultLocalPath = classPath.resolve(RESOURCE_FILE_NAME);
            if (Files.exists(defaultLocalPath) && Files.isReadable(defaultLocalPath)) {
                defaultResource.load(Files.newInputStream(defaultLocalPath));
            }

            try (Stream<Path> paths = Files.find(classPath, 1, (b, fa) -> {
                String fileName = b.getFileName().toString();
                return fa.isRegularFile() && fileName.startsWith(RESOURCE_FILE_PREFIX) && fileName.endsWith(RESOURCE_FILE_POSTFIX);
            })) {
                paths.forEach(p -> {
                    String fileName = p.getFileName().toString();
                    String localName = fileName.substring(RESOURCE_FILE_PREFIX.length(), fileName.length() - RESOURCE_FILE_POSTFIX.length());
                    if (!StringUtils.isEmpty(localName)) {
                        Locale locale = null;
                        if (localName.contains("_")) {
                            String[] splits = localName.split("_");
                            if (splits.length == 2 && !StringUtils.isEmpty(splits[0]) && !StringUtils.isEmpty(splits[1])) {
                                locale = new Locale(splits[0], splits[1]);
                            }
                        } else {
                            locale = new Locale(localName);
                        }
                        if (locale != null) {
                            Properties properties = new Properties();
                            try {
                                if (Files.exists(p) && Files.isReadable(p)) {
                                    properties.load(Files.newInputStream(p));
                                }
                                localeResources.put(locale, properties);
                            } catch (IOException e) {
                                throw new NutException("Resource File Read Fail.", e);
                            }
                        }
                    }
                });
            }
            if (fileSystem != FileSystems.getDefault()) {
                fileSystem.close();
            }
        } catch (URISyntaxException e) {
            throw new NutException("URI Error", e);
        } catch (IOException e) {
            throw new NutException("Resource File Read Fail.", e);
        }
    }

    /**
     * 获取所有本地消息资源对象
     * @return 所有本地消息资源对象
     */
    public Map<Locale, Properties> getLocaleResources() {
        return localeResources;
    }

    /**
     * 获取指定的本地消息资源对象
     * @param locale 指定的本地对象
     * @return 指定的本地消息资源对象
     */
    public Properties getLocaleResource(Locale locale) {
        return localeResources.get(locale);
    }

    /**
     * 获取默认的消息资源对象
     * @return 默认的消息资源对象
     */
    public Properties getDefaultResource() {
        return defaultResource;
    }
}
